use serde::{Deserialize, Deserializer, Serialize};
use snafu::Snafu;
use std::{
    fmt::{Display, Formatter},
    str::FromStr,
};

#[derive(Serialize, Debug, Clone, PartialEq, Eq, Ord, PartialOrd, Default)]
pub struct ResourceVersion(String);

#[derive(Debug, Snafu, Serialize)]
pub enum Error {}

impl<'de> Deserialize<'de> for ResourceVersion {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let v = <String as Deserialize>::deserialize(deserializer)?;
        ResourceVersion::new(v).map_err(|e| serde::de::Error::custom(e.to_string()))
    }
}

impl Display for ResourceVersion {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl TryFrom<String> for ResourceVersion {
    type Error = Error;

    fn try_from(value: String) -> Result<Self, Self::Error> {
        Ok(ResourceVersion { 0: value })
    }
}

impl FromStr for ResourceVersion {
    type Err = Error;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        Self::try_from(s.to_string())
    }
}

impl From<ResourceVersion> for String {
    fn from(value: ResourceVersion) -> Self {
        value.0
    }
}

impl ResourceVersion {
    pub fn new(version: impl ToOwned<Owned = String>) -> Result<Self, Error> {
        Ok(ResourceVersion {
            0: version.to_owned(),
        })
    }
}
